package com.yinshan.avchatkit.ui;

import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Rect;
import android.os.Build;
import android.os.Handler;
import android.support.v4.content.LocalBroadcastManager;
import android.text.TextUtils;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Chronometer;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.hjq.toast.ToastUtils;
import com.yinshan.avchatkit.AVChatKit;
import com.yinshan.avchatkit.R;
import com.yinshan.avchatkit.activity.AVChatActivity;
import com.yinshan.avchatkit.common.permission.BaseMPermission;
import com.yinshan.avchatkit.common.widgets.ToggleListener;
import com.yinshan.avchatkit.common.widgets.ToggleState;
import com.yinshan.avchatkit.common.widgets.ToggleView;
import com.yinshan.avchatkit.common.widgets.ViewfinderView;
import com.yinshan.avchatkit.constant.AVChatExitCode;
import com.yinshan.avchatkit.controll.AVChatController;
import com.yinshan.avchatkit.module.AVChatControllerCallback;
import com.netease.nimlib.sdk.avchat.AVChatManager;
import com.netease.nimlib.sdk.avchat.constant.AVChatType;
import com.netease.nimlib.sdk.avchat.constant.AVChatVideoScalingType;
import com.netease.nimlib.sdk.avchat.model.AVChatData;
import com.netease.nimlib.sdk.avchat.video.AVChatCameraCapturer;
import com.netease.nimlib.sdk.avchat.video.AVChatSurfaceViewRenderer;
import com.netease.nrtc.video.render.IVideoRender;

import java.util.List;

/**
 * 视频界面变化及点击事件
 * Created by winnie on 2017/12/11.
 */

public class AVChatVideoUI implements View.OnClickListener, ToggleListener {

    // constant
    private static final int PEER_CLOSE_CAMERA = 0;
    private static final int LOCAL_CLOSE_CAMERA = 1;
    private static final int AUDIO_TO_VIDEO_WAIT = 2;
    private static final int TOUCH_SLOP = 10;
    private static final String TAG = AVChatVideoUI.class.getSimpleName();

    private final String[] BASIC_PERMISSIONS = new String[]{Manifest.permission.CAMERA,};

    /**
     * surface view
     */
    private LinearLayout largeSizePreviewLayout;
    private FrameLayout smallSizePreviewFrameLayout;
    private LinearLayout smallSizePreviewLayout;
    private ImageView smallSizePreviewCoverImg;//stands for peer or local close camera
    private TextView largeSizePreviewCoverLayout;//stands for peer or local close camera
    private ViewfinderView faceDistinguish;//人脸识别框框
    private TextView txtCameraError;

    /**
     * video view
     */
    //顶部控制按钮
    //中间控制按钮
    private View middleRoot;
    private TextView notifyTV;
    //底部控制按钮
    private View bottomRoot;
    private Chronometer time;
    private ToggleView switchCameraToggle;
    //摄像头权限提示显示
    private View permissionRoot;
    //render
    private AVChatSurfaceViewRenderer smallRender;
    private AVChatSurfaceViewRenderer largeRender;

    // state
    private boolean surfaceInit = false;
    private boolean videoInit = false;
    private boolean shouldEnableToggle = false;
    private boolean canSwitchCamera = false;
    private boolean isPeerVideoOff = false;
    private boolean isLocalVideoOff = false;
    private boolean localPreviewInSmallSize = true;
    private boolean isInReceiveing = false;

    // data
    private AVChatData avChatData;
    private String account;
    private String displayName;
    private int bottomRootHeight = 0;

    private String largeAccount; // 显示在大图像的用户id
    private String smallAccount; // 显示在小图像的用户id


    private Context context;
    private View root;
    private AVChatController avChatController;
    private boolean isReleasedVideo = false;

    public AVChatVideoUI(Context context, View root, AVChatData avChatData, String displayName,
                         AVChatController avChatController) {
        this.context = context;
        this.displayName = displayName;
        this.root = root;
        this.avChatData = avChatData;
        this.avChatController = avChatController;
        this.smallRender = new AVChatSurfaceViewRenderer(context);
        this.largeRender = new AVChatSurfaceViewRenderer(context);
    }

    /**
     * ********************** surface 初始化 **********************
     */

    private void findSurfaceView() {
        if (surfaceInit) {
            return;
        }
        View surfaceView = root.findViewById(R.id.avchat_surface_layout);
        if (surfaceView != null) {
            smallSizePreviewFrameLayout = surfaceView.findViewById(R.id.small_size_preview_layout);
            smallSizePreviewLayout = surfaceView.findViewById(R.id.small_size_preview);
            smallSizePreviewCoverImg = surfaceView.findViewById(R.id.smallSizePreviewCoverImg);
            txtCameraError = surfaceView.findViewById(R.id.txt_camera_status);

            largeSizePreviewLayout = surfaceView.findViewById(R.id.large_size_preview);
            largeSizePreviewCoverLayout = surfaceView.findViewById(R.id.notificationLayout);

            surfaceInit = true;
        }
    }


    private IVideoRender remoteRender;
    private IVideoRender localRender;

    // 大小图像显示切换
    public void switchRender(String user1, String user2) {
        String remoteId = TextUtils.equals(user1, AVChatKit.getAccount()) ? user2 : user1;

        if (remoteRender == null && localRender == null) {
            localRender = smallRender;
            remoteRender = largeRender;
        }
        //交换
        IVideoRender render = localRender;
        localRender = remoteRender;
        remoteRender = render;

        //断开SDK视频绘制画布
        AVChatManager.getInstance().setupLocalVideoRender(null, false, 0);
        AVChatManager.getInstance().setupRemoteVideoRender(remoteId, null, false, 0);

        //重新关联上画布
        AVChatManager.getInstance().setupLocalVideoRender(localRender, false, AVChatVideoScalingType.SCALE_ASPECT_BALANCED);
        AVChatManager.getInstance().setupRemoteVideoRender(remoteId, remoteRender, false, AVChatVideoScalingType.SCALE_ASPECT_BALANCED);

    }

    /**
     * ************************** video 初始化 ***********************
     */
    private void findVideoViews() {
        if (videoInit)
            return;
        View videoRoot = root.findViewById(R.id.avchat_video_layout);

        middleRoot = videoRoot.findViewById(R.id.avchat_video_middle_control);
        bottomRoot = videoRoot.findViewById(R.id.avchat_video_bottom_control);
        notifyTV = videoRoot.findViewById(R.id.avchat_video_notify);
        permissionRoot = videoRoot.findViewById(R.id.avchat_video_permission_control);

        ImageView refuseTV = middleRoot.findViewById(R.id.refuse);
        ImageView receiveTV = middleRoot.findViewById(R.id.receive);
        refuseTV.setOnClickListener(this);
        receiveTV.setOnClickListener(this);


        time = bottomRoot.findViewById(R.id.avchat_video_time);
        faceDistinguish = bottomRoot.findViewById(R.id.vfaceView);
        switchCameraToggle = new ToggleView(bottomRoot.findViewById(R.id.avchat_switch_camera), ToggleState.DISABLE, this);
        ImageView hangUpImg = bottomRoot.findViewById(R.id.avchat_video_logout);
        hangUpImg.setOnClickListener(this);

        videoInit = true;
    }

    public void onResume() {
        surfaceViewFixBefore43(smallSizePreviewLayout, largeSizePreviewLayout);
    }

    public void onDestroy() {
        if (time != null) {
            time.stop();
        }
    }

    /**
     * ********************** 视频流程 **********************
     */

    public void showIncomingCall(AVChatData avChatData) {
        this.avChatData = avChatData;
        this.account = avChatData.getAccount();

        findSurfaceView();
        findVideoViews();

        showNotify(String.format("工号为%s的专员请求和您视频通话", avChatData.getExtra()), true);
        setRefuseReceive(true);
        setBottomRoot(false);
    }

    public void doOutgoingCall(String account, String exteraMsg) {
        this.account = account;

        findSurfaceView();
        findVideoViews();

        showNotify(R.string.avchat_video_call_request, true);
        setRefuseReceive(false);
        shouldEnableToggle = true;
        enableCameraToggle();   //使用音视频预览时这里可以开启切换摄像头按钮
        setBottomRoot(true);

        avChatController.doCalling(account, exteraMsg, new AVChatControllerCallback<AVChatData>() {
            @Override
            public void onSuccess(AVChatData data) {
                avChatData = data;
                avChatController.setAvChatData(data);
                List<String> deniedPermissions = BaseMPermission.getDeniedPermissions((Activity) context, BASIC_PERMISSIONS);
                if (deniedPermissions != null && !deniedPermissions.isEmpty()) {
                    showNoneCameraPermissionView(true);
                    return;
                }
                canSwitchCamera = true;
                initLargeSurfaceView(AVChatKit.getAccount());
                //发出成功发起视频广播
                Intent intent = new Intent();
                intent.setAction(AVChatActivity.ACTION_SINGAL_STATUS);
                intent.putExtra(AVChatActivity.KEY_FACE_STATUS, AVChatActivity.FACE_STATUS_SERVER_START);
                intent.putExtra("channelID", "" + data.getChatId());
                LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
            }

            @Override
            public void onFailed(int code, String errorMsg) {
                if (code == 11001) {
                    ToastUtils.show("对方不在线");
                }
                closeSession();
            }
        });
    }

    public void showVideoInitLayout() {
        findSurfaceView();
        findVideoViews();

        enableToggle();
        setTime();
        setBottomRoot(true);
        setRefuseReceive(false);
        showNoneCameraPermissionView(false);
        showNotify(String.format("工号为%s的专员负责为您完成视频面签", displayName), true);
    }

    // 小图像surface view 初始化
    public void initSmallSurfaceView(String account) {
        smallAccount = account;
        smallSizePreviewFrameLayout.setVisibility(View.VISIBLE);

        // 设置画布，加入到自己的布局中，用于呈现视频图像
        AVChatManager.getInstance().setupLocalVideoRender(null, false, AVChatVideoScalingType.SCALE_ASPECT_BALANCED);
        AVChatManager.getInstance().setupLocalVideoRender(smallRender, false, AVChatVideoScalingType.SCALE_ASPECT_BALANCED);
        addIntoSmallSizePreviewLayout(smallRender);

        smallSizePreviewFrameLayout.bringToFront();
        localRender = smallRender;
        localPreviewInSmallSize = true;
    }

    private void addIntoSmallSizePreviewLayout(SurfaceView surfaceView) {
        smallSizePreviewCoverImg.setVisibility(View.GONE);
        if (surfaceView.getParent() != null) {
            ((ViewGroup) surfaceView.getParent()).removeView(surfaceView);
        }
        smallSizePreviewLayout.removeAllViews();
        smallSizePreviewLayout.addView(surfaceView);
        surfaceView.setZOrderMediaOverlay(true);
        smallSizePreviewLayout.setVisibility(View.VISIBLE);
    }

    // 大图像surface view 初始化
    public void initLargeSurfaceView(String account) {
        // 设置画布，加入到自己的布局中，用于呈现视频图像
        // account 要显示视频的用户帐号
        largeAccount = account;
        if (AVChatKit.getAccount().equals(account)) {
            AVChatManager.getInstance().setupLocalVideoRender(largeRender, false, AVChatVideoScalingType.SCALE_ASPECT_BALANCED);
        } else {
            AVChatManager.getInstance().setupRemoteVideoRender(account, largeRender, false, AVChatVideoScalingType.SCALE_ASPECT_BALANCED);
        }
        addIntoLargeSizePreviewLayout(largeRender);
        remoteRender = largeRender;
    }

    private void addIntoLargeSizePreviewLayout(SurfaceView surfaceView) {
        if (surfaceView.getParent() != null) {
            ((ViewGroup) surfaceView.getParent()).removeView(surfaceView);
        }
        largeSizePreviewLayout.removeAllViews();
        largeSizePreviewLayout.addView(surfaceView);
        surfaceView.setZOrderMediaOverlay(false);
        largeSizePreviewCoverLayout.setVisibility(View.GONE);
    }

    public void onAudioToVideoAgree(String largeAccount) {
        showVideoInitLayout();
        account = largeAccount;

        switchCameraToggle.off(false);

        //打开视频
        isReleasedVideo = false;
        smallRender = new AVChatSurfaceViewRenderer(context);
        largeRender = new AVChatSurfaceViewRenderer(context);

        //打开视频
        AVChatManager.getInstance().enableVideo();
        AVChatManager.getInstance().startVideoPreview();

        initSmallSurfaceView(AVChatKit.getAccount());
        // 是否在发送视频 即摄像头是否开启
        if (AVChatManager.getInstance().isLocalVideoMuted()) {
            AVChatManager.getInstance().muteLocalVideo(false);
            localVideoOn();
        }

        initLargeSurfaceView(largeAccount);
        showFaceView(avChatController.isRecording());
    }

    /********************** 界面显示 **********************************/

    /**
     * 显示通知信息
     *
     * @param text   通知信息
     * @param isShow 是否显示
     */
    public void showNotify(Object text, boolean isShow) {
        if (isShow) {
            if (text instanceof String) {
                notifyTV.setText(text.toString());
            } else if (text instanceof Integer) {
                notifyTV.setText((int) text);
            }
            notifyTV.setVisibility(View.VISIBLE);
        } else {
            notifyTV.setVisibility(View.GONE);
        }
    }

    /**
     * @param message 通知内容  三秒后消失
     */
    public void showNotify(String message) {
        notifyTV.setVisibility(View.VISIBLE);
        notifyTV.setText(message);
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                notifyTV.setText("");
                notifyTV.setVisibility(View.GONE);
            }
        }, 3000);
    }

    /**
     * 显示拒绝、接通按钮
     *
     * @param visible
     */
    private void setRefuseReceive(boolean visible) {
        middleRoot.setVisibility(visible ? View.VISIBLE : View.GONE);
    }

    private void setBottomRoot(boolean visible) {
        bottomRoot.setVisibility(visible ? View.VISIBLE : View.GONE);
        if (bottomRootHeight == 0) {
            bottomRootHeight = bottomRoot.getHeight();
        }
    }

    /**
     * 显示对方摄像头无效提示
     */
    public void showCameraError() {
        if (null != txtCameraError) {
            txtCameraError.setVisibility(View.VISIBLE);
        }
    }

    // 底部控制开关可用
    private void enableToggle() {
        if (shouldEnableToggle) {
            if (canSwitchCamera && AVChatCameraCapturer.hasMultipleCameras()) {
                switchCameraToggle.enable();
            }
            shouldEnableToggle = false;
        }
    }

    /**
     * 开始计时
     */
    private void setTime() {
        time.setBase(avChatController.getTimeBase());
        time.start();
    }

    public void showNoneCameraPermissionView(boolean show) {
        permissionRoot.setVisibility(show ? View.VISIBLE : View.GONE);
    }

    private void enableCameraToggle() {
        if (shouldEnableToggle) {
            if (canSwitchCamera && AVChatCameraCapturer.hasMultipleCameras())
                switchCameraToggle.enable();
        }
    }

    /**
     * ******************** 点击事件 **********************
     */

    @Override
    public void toggleOn(View v) {
        onClick(v);
    }

    @Override
    public void toggleOff(View v) {
        onClick(v);
    }

    @Override
    public void toggleDisable(View v) {

    }

    @Override
    public void onClick(View v) {
        int i = v.getId();
        if (i == R.id.refuse) {
            doRefuseCall();
        } else if (i == R.id.receive) {
            if (isInReceiveing || avChatController.isCallEstablish.get()) {
                Toast.makeText(context, R.string.avchat_in_switch, Toast.LENGTH_SHORT).show();
            } else {
                doReceiveCall();
            }
        } else if (i == R.id.avchat_video_logout) {
            doHangUp();
        } else if (i == R.id.avchat_switch_camera) {
            avChatController.switchCamera();
        }
    }

    // 拒绝来电
    private void doRefuseCall() {
        avChatController.hangUp(AVChatExitCode.HANGUP);
        closeSession();
    }

    private void doReceiveCall() {
        isInReceiveing = true;
        showNotify(R.string.avchat_connecting, true);
        shouldEnableToggle = true;
        avChatController.receive(AVChatType.VIDEO, new AVChatControllerCallback<Void>() {
            @Override
            public void onSuccess(Void aVoid) {
                isInReceiveing = false;
                canSwitchCamera = true;
            }

            @Override
            public void onFailed(int code, String errorMsg) {
                isInReceiveing = false;
                closeSession();
            }
        });
    }

    private void doHangUp() {
        releaseVideo();
        avChatController.hangUp(AVChatExitCode.HANGUP);
        closeSession();
    }


    public void releaseVideo() {
        if (isReleasedVideo) {
            return;
        }
        isReleasedVideo = true;
        AVChatManager.getInstance().stopVideoPreview();
        AVChatManager.getInstance().disableVideo();
    }

    // 对方打开了摄像头
    private void localVideoOn() {
        isLocalVideoOff = false;
        if (localPreviewInSmallSize) {
            smallSizePreviewCoverImg.setVisibility(View.GONE);
        } else {
            largeSizePreviewCoverLayout.setVisibility(View.GONE);
        }
    }

    // 本地关闭了摄像头
    private void localVideoOff() {
        isLocalVideoOff = true;
        if (localPreviewInSmallSize) {
            closeSmallSizePreview();
        } else {
            showNotificationLayout(LOCAL_CLOSE_CAMERA);
        }
    }

    // 对方关闭了摄像头
    public void peerVideoOff() {
        isPeerVideoOff = true;
        if (localPreviewInSmallSize) { //local preview in small size layout, then peer preview should in large size layout
            showNotificationLayout(PEER_CLOSE_CAMERA);
        } else {
            closeSmallSizePreview();
        }
    }

    // 对方打开了摄像头
    public void peerVideoOn() {
        isPeerVideoOff = false;
        if (localPreviewInSmallSize) {
            largeSizePreviewCoverLayout.setVisibility(View.GONE);
        } else {
            smallSizePreviewCoverImg.setVisibility(View.GONE);
        }
    }

    // 关闭小窗口
    private void closeSmallSizePreview() {
        smallSizePreviewCoverImg.setVisibility(View.VISIBLE);
    }

    // 界面提示
    private void showNotificationLayout(int closeType) {
        if (largeSizePreviewCoverLayout == null) {
            return;
        }
        TextView textView = largeSizePreviewCoverLayout;
        switch (closeType) {
            case PEER_CLOSE_CAMERA:
                textView.setText(R.string.avchat_peer_close_camera);
                break;
            case LOCAL_CLOSE_CAMERA:
                textView.setText(R.string.avchat_local_close_camera);
                break;
            case AUDIO_TO_VIDEO_WAIT:
                textView.setText(R.string.avchat_audio_to_video_wait);
                break;
            default:
                return;
        }
        largeSizePreviewCoverLayout.setVisibility(View.VISIBLE);
    }


    /**
     * 录制入口
     */
    public void doToggleRecord() {
        if (!avChatController.isRecording()) {
            showNotify(R.string.avchat_start_face, true);
            showFaceView(true);
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    recordToggle();
                }
            }, 3000);
        }
    }

    /**
     * 开始或停止录制
     */
    private void recordToggle() {
        avChatController.toggleRecord(new AVChatController.RecordCallback() {
            @Override
            public void onRecordUpdate(boolean isRecording) {
//                showFaceView(isRecording);
                if (isRecording) {
                    handler.removeCallbacks(runnable);
                    handler.post(runnable);
                }
            }
        });
    }

    /**
     * 人脸识别计时
     */
    private Handler handler = new Handler();
    private int sceondTime = 0;
    private Runnable runnable = new Runnable() {
        @Override
        public void run() {
            if (sceondTime++ < 6) {
                showNotify(String.format("正在进行人脸识别，%ss", sceondTime), true);
                handler.postDelayed(runnable, 1000);
            } else {
                handler.removeCallbacks(this);
                sceondTime = 0;
                recordToggle();
            }
        }
    };

    /**
     * 录制界面预览
     *
     * @param show 显示/隐藏
     */
    public void showFaceView(boolean show) {
        if (show) {
            faceDistinguish.setVisibility(View.VISIBLE);
        } else {
            faceDistinguish.setVisibility(View.GONE);
            showNotify("", false);
        }
    }

    public void resetRecordTip() {
        avChatController.setRecording(false);
        showFaceView(false);
    }

    private void closeSession() {
        ((Activity) context).finish();
    }

    public AVChatData getAvChatData() {
        return avChatData;
    }

    private void surfaceViewFixBefore43(ViewGroup front, ViewGroup back) {
        if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN_MR2) {
            if (back.getChildCount() > 0) {
                View child = back.getChildAt(0);
                back.removeView(child);
                back.addView(child);
            }

            if (front.getChildCount() > 0) {
                View child = front.getChildAt(0);
                front.removeView(child);
                front.addView(child);
            }
        }
    }

}
